/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package co.edu.distribuidos.mundo;

import co.edu.distribuidos.conectividad.ServidorJXTA;
import co.edu.distribuidos.tiempo.AdministradorTiempo;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Date;

/**
 *
 * @author alvar-go@uniandes.edu.co
 */
public class AdministradorArchivos {

    private final static String[] EXTENSIONES_TEXTO = {".txt", ".pdf", ".doc", ".docx"};

    private final static String[] EXTENSIOENS_AUDIO = {".mp3", ".wav", ".wma"};

    private final static String[] EXTENSIOENS_IMAGEN = {".mpg", ".avi", ".mpeg"};

    private final static String CARPETA_COMPARTIDA = "./data/";

    private final static String RUTA_PERSISTENCIA = "./data/persistencia";

    private final static String ARCHIVO_PERSISTENCIA = "persistencia";

    public final static String AUDIO = "Audio";

    public final static String TEXTO = "Documento";

    public final static String IMAGEN = "Imagen";

    private final static String INVALIDO = "Invalido";

    private ArrayList<Archivo> documentos;

    private ArrayList<Archivo> audios;

    private ArrayList<Archivo> imagenes;

    private ServidorJXTA servidor;


    public AdministradorArchivos()throws Exception{
        documentos = new ArrayList<Archivo>();
        audios = new ArrayList<Archivo>();
        imagenes = new ArrayList<Archivo>();
        servidor = new ServidorJXTA("Nodo Prueba");
        cargar();
    }

    public void iniciarJXTA(){
        servidor.recibirConexiones();
    }

    public void detenerJXTA(){
        servidor.detenerJXTA();
    }

    public String darTipoArchivo(String nombre){
        if(esTexto(nombre)){
            return TEXTO;
        }
        else if(esAudio(nombre)){
            return AUDIO;
        }
        else if(esImagen(nombre)){
            return IMAGEN;
        }
        else{
            return INVALIDO;
        }
    }

    private boolean esAudio(String nombre){
        boolean esAudio = false;
        for( int i = 0; i < EXTENSIOENS_AUDIO.length && !esAudio; i++){
            if(nombre.toLowerCase().endsWith(EXTENSIOENS_AUDIO[i])){
                esAudio = true;
            }
        }
        return esAudio;
    }

     private boolean esTexto(String nombre){
        boolean esTexto = false;
        for( int i = 0; i < EXTENSIONES_TEXTO.length && !esTexto; i++){
            if(nombre.toLowerCase().endsWith(EXTENSIONES_TEXTO[i])){
                esTexto = true;
            }
        }
        return esTexto;
    }

      private boolean esImagen(String nombre){
        boolean esImagen = false;
        for( int i = 0; i < EXTENSIOENS_IMAGEN.length && !esImagen; i++){
            if(nombre.toLowerCase().endsWith(EXTENSIOENS_IMAGEN[i])){
                esImagen = true;
            }
        }
        return esImagen;
    }

    public void compartirArchivo(File archivo, ArrayList<String> palabrasClave)throws Exception{
        String tipo = darTipoArchivo(archivo.getName());
        if( tipo.equals(INVALIDO)){
            throw new Exception("El tipo de archivo no se puede compartir.");
        }
        else{
            //Se debe buscar si existe el archivo en la red
            Date tiempo = AdministradorTiempo.darTiempo();
            if(tiempo == null ){
                throw new Exception("No fue posible recuperar el tiempo UTC");
            }
            Archivo nuevo = new Archivo(archivo, tiempo, Archivo.LOCAL, palabrasClave);
           if(tipo.equals(AUDIO)){
                audios.add(nuevo);
            }
            else if(tipo.equals(IMAGEN)){
                imagenes.add(nuevo);
            }
            else {
                documentos.add(nuevo);
            }
            String ruta = CARPETA_COMPARTIDA + "/" + tipo;
            File carpeta = new File(ruta);
            if( !carpeta.exists() ){
                carpeta.mkdir();
            }
            File copia = new File(carpeta, archivo.getName());
            if(!copia.exists()){
                copia.createNewFile();
            }
            FileInputStream in = new FileInputStream(archivo);
            FileOutputStream out = new FileOutputStream(copia);
            byte[] buffer = new byte[4096];
            int bytesPorLeer;
            while ((bytesPorLeer = in.read(buffer)) != -1){
                    out.write(buffer, 0, bytesPorLeer);
            }
            out.close();
            in.close();
        }
    }

    public ArrayList<Archivo> darArchivos(String tipo){
        if( tipo.equals(AUDIO)){
            return audios;
        }
        else if(tipo.equals(TEXTO)){
            return documentos;
        }
        else{
            return imagenes;
        }
    }

    public void guardar()throws Exception{
        try {
            File carpeta = new File(RUTA_PERSISTENCIA);
            if(!carpeta.exists()){
                carpeta.mkdir();
            }
            File archivo = new File(carpeta, ARCHIVO_PERSISTENCIA);
            if(!archivo.exists()){
                archivo.createNewFile();
            }
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(archivo));
            oos.writeObject(documentos);
            oos.writeObject(imagenes);
            oos.writeObject(audios);
            oos.close();
        } catch (Exception e) {
            throw new Exception("No fue posible guardar el estado de la aplicación. \n" + e.getMessage());
        }
   }

   private void cargar()throws Exception{
       try {
           File archivo = new File(RUTA_PERSISTENCIA + "/" + ARCHIVO_PERSISTENCIA);
           if(archivo.exists()){
               ObjectInputStream ois = new ObjectInputStream(new FileInputStream(archivo));
               documentos = (ArrayList<Archivo>)ois.readObject();
               imagenes = (ArrayList<Archivo>)ois.readObject();
               audios = (ArrayList<Archivo>)ois.readObject();
               ois.close();
           }
       } catch (Exception e) {
           throw new Exception("No fue posible cargar el estadode la aplicación. \n" + e.getMessage());
       }
   }

   public Archivo darArchivoPorIdentificacion(String identificacion){
       Archivo buscado = null;
       for( int i = 0; i < documentos.size() && buscado ==null; i++){
           Archivo actual = documentos.get(i);
           if(actual.darNombre().equals(identificacion)){
               buscado = actual;
           }
       }
       for( int i = 0; i < audios.size() && buscado ==null; i++){
           Archivo actual = audios.get(i);
           if(actual.darNombre().equals(identificacion)){
               buscado = actual;
           }
       }
       for( int i = 0; i < imagenes.size() && buscado ==null; i++){
           Archivo actual = imagenes.get(i);
           if(actual.darNombre().equals(identificacion)){
               buscado = actual;
           }
       }
       return buscado;
   }

   public ArrayList<Archivo> darArchivosPorPalabrasClave(String[] palabras){
       ArrayList<Archivo> resultado = new ArrayList<Archivo>();
       for( int i = 0; i < documentos.size(); i++){
           Archivo actual = documentos.get(i);
           boolean agregado = false;
           for( int j = 0; j < palabras.length && !agregado; j++){
               if(actual.contienePalabraClave(palabras[j])){
                   resultado.add(actual);
                   agregado = true;
               }
           }
       }
       for( int i = 0; i < audios.size(); i++){
           Archivo actual = audios.get(i);
           boolean agregado = false;
           for( int j = 0; j < palabras.length && !agregado; j++){
               if(actual.contienePalabraClave(palabras[j])){
                   resultado.add(actual);
                   agregado = true;
               }
           }
       }
       for( int i = 0; i < imagenes.size(); i++){
           Archivo actual = imagenes.get(i);
            boolean agregado = false;
           for( int j = 0; j < palabras.length && !agregado; j++){
               if(actual.contienePalabraClave(palabras[j])){
                   resultado.add(actual);
                   agregado = true;
               }
           }
       }
       return resultado;
   }

   public Archivo darDocumentoPorTamanio(long tamanio){
        Archivo resp = null;
        long diferencia = 0;
        for( int i = 0; i < documentos.size(); i++){
            Archivo actual = documentos.get(i);
            if(actual.darExtension().equals("doc")){
                if(resp == null){
                    resp = actual;
                    diferencia = Math.abs(tamanio - resp.darTamanio());
                }
                else{
                    long difActual = Math.abs(tamanio - actual.darTamanio());
                    if( difActual < diferencia ){
                        resp = actual;
                        diferencia = difActual;
                    }
                }
            }
        }
        return resp;
   }

    public void descargarArhivo(String nombre, String propietario) {
        throw new UnsupportedOperationException("Not yet implemented");
    }
}
